﻿namespace MicroCloud.Extensions
{
    #region "实体Hash扩展方法"
    /// <summary>
    /// 实体Hash扩展方法
    /// </summary>
    public static class EntityHashExtensions
    {
        #region "方法"
        #region "获取指定实体的Hash值"
        /// <summary>
        /// 获取指定实体的Hash值
        /// </summary>
        /// <param name="entity">实体对象</param>
        /// <param name="entityType">实体类型</param>
        /// <returns></returns>
        public static string GetHash(this IEntityHash entity, Type entityType = null)
        {
            var builder = BuildHashString(entity, entityType);
            var hash = builder.ToString().ToMD5();
            return hash;
        }
        #endregion

        #endregion

        #region "私有方法"
        #region "构建哈希字符串"
        /// <summary>
        /// 构建哈希字符串
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="entityType"></param>
        /// <returns></returns>
        private static StringBuilder BuildHashString(object entity, Type entityType = null)
        {
            StringBuilder builder = new();
            entityType ??= entity?.GetType();
            // 设置排除字段
            //string[] exceptNames = { "Id", "CreatorId", "CreatedTime", "UpdaterId", "UpdatedTime", "DataVersion", "DeletedTime" };
            List<string> exceptNames = new();
            if (entityType.IsBaseOn(typeof(IEntity<>)))
            {
                exceptNames.Add("Id");
            }
            if (entityType.IsBaseOn(typeof(ICreationAudited<>)) || entityType.IsBaseOn(typeof(ICreationAudited)))
            {
                exceptNames.Add("CreatorId");
            }
            if (entityType.IsBaseOn(typeof(ICreatedTime)))
            {
                exceptNames.Add("CreatedTime");
            }
            if (entityType.IsBaseOn(typeof(IUpdateAudited<>)) || entityType.IsBaseOn(typeof(IUpdateAudited)))
            {
                exceptNames.Add("UpdaterId");
            }
            if (entityType.IsBaseOn(typeof(IUpdatedTime)))
            {
                exceptNames.Add("UpdatedTime");
            }
            if (entityType.IsBaseOn(typeof(IDataVersion)))
            {
                exceptNames.Add("DataVersion");
            }
            if (entityType.IsBaseOn(typeof(ISoftDeletable)))
            {
                exceptNames.Add("DeletedTime");
            }

            PropertyInfo[] properties = entityType?.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                ?.Where(m => m.CanWrite && !exceptNames.Contains(m.Name) && !m.HasAttribute<HashIgnoreAttribute>())?.ToArray();
            foreach (PropertyInfo property in properties)
            {
                var entityValue = property.GetValue(entity);
                if (property.PropertyType.IsClass || property.PropertyType.IsEnumerable())
                {
                    entityValue = entityValue.ToJsonString();
                }
                builder.Append(entityValue);
            }
            return builder;
        }
        #endregion

        #endregion


    }
    #endregion

}
